package com.chiancloud.shield.server.services.workflow;

import com.google.common.base.Preconditions;
import org.apache.hadoop.service.CompositeService;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.service.ServiceStateChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Created by wanghui on 14-8-20.
 */
public class WorkflowCompositeService extends CompositeService implements ServiceParent,ServiceStateChangeListener {
    private static final Logger LOG =
            LoggerFactory.getLogger(WorkflowCompositeService.class);

    public WorkflowCompositeService(String name) {
        super(name);
    }

    public WorkflowCompositeService() {
        this("WorkflowCompositeService");
    }

    public WorkflowCompositeService(String name, Service... children) {
        this(name);
        for (Service child : children) {
            addService(child);
        }
    }

    public WorkflowCompositeService(String name, List<Service> children) {
        this(name);
        for (Service child : children) {
            addService(child);
        }
    }


    @Override
    public synchronized void addService(Service service) {
        Preconditions.checkArgument(service != null, "null service argument");
        service.registerServiceListener(this);
        super.addService(service);
    }

    @Override
    public void stateChanged(Service child) {
        if (isInState(STATE.STARTED) && child.isInState(STATE.STOPPED)) {
            Throwable failureCause = child.getFailureCause();
            if (failureCause != null) {
                LOG.info("Child service " + child + " failed", failureCause);
                Exception e = (failureCause instanceof Exception) ?
                        (Exception) failureCause : new Exception(failureCause);
                noteFailure(e);
                stop();
            } else {
                LOG.info("Child service completed {}", child);
                if (areAllChildrenStopped()) {
                    LOG.info("All children are halted: stopping");
                    stop();
                }
            }
        }
    }
    private boolean areAllChildrenStopped() {
        List<Service> children = getServices();
        boolean stopped = true;
        for (Service child : children) {
            if (!child.isInState(STATE.STOPPED)) {
                stopped = false;
                break;
            }
        }
        return stopped;
    }
}
